#pragma once
#include "platform.hpp"
#include "stdlib/timestamp.hpp"
using namespace JHCPP::stdlib;
#include <vector>

#if defined(JH_OS_WINDOWS)
#include <Windows.h>
#elif defined(JH_OS_LINUX)

#endif

namespace JHCPP
{
	namespace filesys
	{
	#if defined(JH_OS_WINDOWS)
		class CFileImpl
		{
		protected:
			typedef UInt64 FileSizeImpl;

			CFileImpl();
			CFileImpl(const std::string& path);
			virtual ~CFileImpl();
			void swapImpl(CFileImpl& file);
			void setPathImpl(const std::string& path);
			const std::string& getPathImpl() const;
			bool existsImpl() const;
			bool canReadImpl() const;
			bool canWriteImpl() const;
			bool canExecuteImpl() const;
			bool isFileImpl() const;
			bool isDirectoryImpl() const;
			bool isLinkImpl() const;
			bool isDeviceImpl() const;
			bool isHiddenImpl() const;
			CTimeStamp createdImpl() const;
			CTimeStamp getLastModifiedImpl() const;
			void setLastModifiedImpl(const CTimeStamp& ts);
			FileSizeImpl getSizeImpl() const;
			void setSizeImpl(FileSizeImpl size);
			void setWriteableImpl(bool flag = true);		
			void setExecutableImpl(bool flag = true);		
			void copyToImpl(const std::string& path) const;
			void renameToImpl(const std::string& path);
			void removeImpl();
			bool createFileImpl();
			bool createDirectoryImpl();
			static void handleLastErrorImpl(const std::string& path);

		private:
			std::string m_path;

			friend class CFileHandle;
		};

	#elif defined(JH_OS_LINUX)
		class CFileImpl
		{
		protected:
			typedef UInt64 FileSizeImpl;

			CFileImpl();
			CFileImpl(const std::string& path);
			virtual ~CFileImpl();
			void swapImpl(CFileImpl& file);
			void setPathImpl(const std::string& path);
			const std::string& getPathImpl() const;
			bool existsImpl() const;
			bool canReadImpl() const;
			bool canWriteImpl() const;
			bool canExecuteImpl() const;
			bool isFileImpl() const;
			bool isDirectoryImpl() const;
			bool isLinkImpl() const;
			bool isDeviceImpl() const;
			bool isHiddenImpl() const;
			CTimeStamp createdImpl() const;
			CTimeStamp getLastModifiedImpl() const;
			void setLastModifiedImpl(const CTimeStamp& ts);
			FileSizeImpl getSizeImpl() const;
			void setSizeImpl(FileSizeImpl size);
			void setWriteableImpl(bool flag = true);		
			void setExecutableImpl(bool flag = true);		
			void copyToImpl(const std::string& path) const;
			void renameToImpl(const std::string& path);
			void removeImpl();
			bool createFileImpl();
			bool createDirectoryImpl();
			static void handleLastErrorImpl(const std::string& path);

		private:
			std::string m_path;
		};
	#endif

		class CPath;

		class CFile: private CFileImpl
			/// The File class provides methods for working with a file.
		{
		public:
			typedef FileSizeImpl FileSize;

			CFile();
			CFile(const std::string& path);
			CFile(const char* path);
			CFile(const CPath& path);
			CFile(const CFile& file);
			virtual ~CFile();
			CFile& operator = (const CFile& file);
			CFile& operator = (const std::string& path);
			CFile& operator = (const char* path);
			CFile& operator = (const CPath& path);

			void swap(CFile& file);
			const std::string& path() const;

			bool exists() const;
			bool canRead() const;
			bool canWrite() const;
			bool canExecute() const;
			bool isFile() const;
			bool isLink() const;
			bool isDirectory() const;
			bool isDevice() const;
			bool isHidden() const;

			CTimeStamp created() const;
			CTimeStamp getLastModified() const;
			CFile& setLastModified(const CTimeStamp& ts);

			FileSize getSize() const;
			CFile& setSize(FileSize size);
	
			CFile& setWriteable(bool flag = true);
			CFile& setReadOnly(bool flag = true);
			CFile& setExecutable(bool flag = true);
			void copyTo(const std::string& path) const;

			void moveTo(const std::string& path);
			void renameTo(const std::string& path);
			void remove(bool recursive = false);

			bool createFile();
			bool createDirectory();
			void createDirectories();

			void list(std::vector<std::string>& files) const;
			void list(std::vector<CFile>& files) const;


			bool operator == (const CFile& file) const;
			bool operator != (const CFile& file) const;
			bool operator <  (const CFile& file) const;
			bool operator <= (const CFile& file) const;
			bool operator >  (const CFile& file) const;
			bool operator >= (const CFile& file) const;

			static void handleLastError(const std::string& path);

		protected:
			void copyDirectory(const std::string& path) const;
		};

	}//end of namespace filesys
}//end of namespace JHCPP